package com.shenmazong.library.service.impl;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shenmazong.library.entity.*;
import com.shenmazong.library.mapper.TbTaskChapterMapper;
import com.shenmazong.library.mapper.TbTaskSkillDetailMapper;
import com.shenmazong.library.mapper.TbTaskSkillLibraryMapper;
import com.shenmazong.library.mapper.TbTaskTheoryLibraryMapper;
import com.shenmazong.library.service.TaskLibraryService;
import com.shenmazong.util.ChooseIsNull;
import com.shenmazong.util.MyTimeUtil;
import com.shenmazong.util.OssUploadTemplate;
import com.shenmazong.utils.ResultResponse;
import com.shenmazong.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.document.Document;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;

import static com.shenmazong.config.MqConfig.THEORY_QUEUE;


/**
 *serviceImpl Qi
 */
@Service
@Slf4j
public class TaskLibraryServiceImpl extends ServiceImpl<TbTaskTheoryLibraryMapper, TbTaskTheoryLibrary>
    implements TaskLibraryService {

    @Autowired
    private  TbTaskTheoryLibraryMapper  theoryMapper;
    @Autowired
    private TbTaskSkillLibraryMapper skillMapper;
    @Autowired
    private TbTaskSkillDetailMapper detailMapper;
    @Autowired
    private TbTaskChapterMapper chapterMapper;
    @Autowired
    private OssUploadTemplate ossUploadTemplate;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private RabbitTemplate mqTemplate;
    @Autowired
    private ElasticsearchRestTemplate esTemplate;

    @Override
    public ResultResponse onLineInputTaskTheory(TaskTheoryListVo taskTheoryListVo) {
        //获取数据集合
        List<TbTaskTheoryLibrary> list = taskTheoryListVo.getLibraryList();
        if(list==null){
            log.info("新增失败,数据集合为空");
            return ResultResponse.FAILED("新增失败,数据集合为空");
        }
        //遍历
        for (TbTaskTheoryLibrary theory : list) {
            //构造对象属性
            theory.setTeacherId(taskTheoryListVo.getTeacherId());
            theory.setChapterId(taskTheoryListVo.getChapterId());
            theory.setCourseId(taskTheoryListVo.getCourseId());
            theory.setSchoolId(taskTheoryListVo.getSchoolId());
            //存入数据库
            theoryMapper.insert(theory);
            //发送到同步es的队列
            mqTemplate.convertAndSend(THEORY_QUEUE,theory.getTheoryId()+",save");
        }
        return ResultResponse.SUCCESS();
    }

    @Override
    public ResultResponse uploadFileInputTaskTheory(MultipartFile file) throws IOException {
        if (file==null|| file.getSize()==0){
            log.info("文件为空");
            return ResultResponse.FAILED("请选择文件，重新上传");
        }
        String filename = file.getOriginalFilename();
        if (!(filename.endsWith(".xls")|| filename.endsWith(".xlsx"))){
            log.info("文件上传格式错误，请重新上传");
            return ResultResponse.FAILED("文件上传格式错误，重新上传");
        }
        //构造ExcelReader对象
        ExcelReader reader = ExcelUtil.getReader(file.getInputStream());
        //处理别名
        reader.addHeaderAlias("知识点","knowledge");
        reader.addHeaderAlias("题干","theoryTitle");
        reader.addHeaderAlias("类型","theoryType");
        reader.addHeaderAlias("选项A","option1");
        reader.addHeaderAlias("选项B","option2");
        reader.addHeaderAlias("选项C","option3");
        reader.addHeaderAlias("选项D","option4");
        reader.addHeaderAlias("选项E","option5");
        reader.addHeaderAlias("选项F","option6");
        reader.addHeaderAlias("答案（选择填ABCDEF，中间不能有空格 判断填A或B，填空题多空用逗号分隔）","answers");
        reader.addHeaderAlias("试题解析（选填）","analysis");
        reader.addHeaderAlias("出题人","person");
        //生成list集合
        List<TbTaskTheoryLibrary> list = reader.readAll(TbTaskTheoryLibrary.class);
        //关闭流
        reader.close();
        //所有数据长度
        int all = list.size();
        log.info("文件上传成功,共{}条数据",all);
        //数据效验
        log.info("开始数据效验");
        List<TbTaskTheoryLibrary> successList = new ArrayList<>();
        List<TbTaskTheoryLibrary> errorList = new ArrayList<>();

        int nullNum = 0;
        for (TbTaskTheoryLibrary library : list) {
            //读取内容为空
            if(library==null){
                nullNum++;
                continue;
            }
            //非空项为空 则加入错误集合
            if(StringUtils.checkValNull(library.getTheoryType())
                    || StringUtils.checkValNull(library.getTheoryTitle())
                    || StringUtils.checkValNull(library.getAnswers())){
                errorList.add(library);
                continue;
            }
            //类型内容判断
            if(!(library.getTheoryType().startsWith("1-单选") || library.getTheoryType().startsWith("2-多选") || library.getTheoryType().startsWith("0-判断"))){
                errorList.add(library);
                continue;
            }
            successList.add(library);
        }

        //错误数据集合长度
        int errorSize = errorList.size();
        //未去重的长度
        int sc1 = successList.size();
        //list去重
        HashSet<TbTaskTheoryLibrary> set = new HashSet<>(successList);
        successList.clear();
        successList.addAll(set);

        //类型内容处理
        for (TbTaskTheoryLibrary library : successList) {
            if (library.getTheoryType().startsWith("1-单选")){
                library.setTheoryType("1-单选题");
                continue;
            }
            if (library.getTheoryType().startsWith("2-多选")){
                library.setTheoryType("2-多选题");
                continue;
            }
            if (library.getTheoryType().startsWith("0-判断")){
                library.setTheoryType("0-判断题");
            }
        }

        //去重后长度
        int sc2 = successList.size();

        log.info("数据效验完成");
        String msg = "共上传 "+all+" 条数据,其中空数据"+nullNum+"条,错误数据共 "+errorSize+" 条,重复数据 "+(sc1-sc2)+" 条,效验通过的数据共 "+sc2+" 条";
        log.info(msg);
        return ResultResponse.SUCCESS(200,msg,successList);
    }

    @Override
    public ResultResponse updateTaskTheory(TbTaskTheoryLibrary tbTaskTheoryLibrary) {
        String nowTime = MyTimeUtil.getNowTimeToString();
        tbTaskTheoryLibrary.setUpdateTime(nowTime);
        tbTaskTheoryLibrary.setToEs(0);
        int i = theoryMapper.updateById(tbTaskTheoryLibrary);
        if(i<1){
            return ResultResponse.FAILED("修改失败");
        }
        //发送到同步es的队列
        mqTemplate.convertAndSend(THEORY_QUEUE,tbTaskTheoryLibrary.getTheoryId()+",save");

        return ResultResponse.SUCCESS(theoryMapper.selectById(tbTaskTheoryLibrary.getTheoryId()));
    }

    @Override
    public ResultResponse deleteTaskTheoryByTheoryIds(BatchChooseIdVo chooseIdVo) {
        if (ChooseIsNull.idsIsNull(chooseIdVo)){
            return ResultResponse.FAILED("未选择要删除的数据");
        }
        int i = theoryMapper.deleteBatchIds(chooseIdVo.getIds());
        if(i<1){
            return ResultResponse.FAILED("删除失败");
        }
        //发送到同步es的队列
        for (Long id : chooseIdVo.getIds()) {
            mqTemplate.convertAndSend(THEORY_QUEUE,id+",del");
        }

        return ResultResponse.SUCCESS();
    }

    @Override
    public ResultResponse deleteTaskTheoryByCourseIds(BatchChooseIdVo chooseIdVo) {
        if (ChooseIsNull.idsIsNull(chooseIdVo)){
            return ResultResponse.FAILED("未选择要删除的数据");
        }
        for (Long id : chooseIdVo.getIds()) {
            List<TbTaskTheoryLibrary> list = theoryMapper.selectList(new QueryWrapper<TbTaskTheoryLibrary>().lambda().eq(TbTaskTheoryLibrary::getCourseId, id));
            int i = theoryMapper.delete(new QueryWrapper<TbTaskTheoryLibrary>().lambda().eq(TbTaskTheoryLibrary::getCourseId, id));
            if(i<1){
                return ResultResponse.FAILED("删除失败");
            }
            //发送到同步es的队列
            for (TbTaskTheoryLibrary library : list) {
                mqTemplate.convertAndSend(THEORY_QUEUE,library.getTheoryId()+",del");
            }
        }
        return ResultResponse.SUCCESS();
    }

    @Override
    public ResultResponse deleteTaskTheoryByChapterIds(BatchChooseIdVo chooseIdVo) {
        if (ChooseIsNull.idsIsNull(chooseIdVo)){
            return ResultResponse.FAILED("未选择要删除的数据");
        }
        for (Long id : chooseIdVo.getIds()) {
            List<TbTaskTheoryLibrary> list = theoryMapper.selectList(new QueryWrapper<TbTaskTheoryLibrary>().lambda().eq(TbTaskTheoryLibrary::getChapterId, id));
            int i = theoryMapper.delete(new QueryWrapper<TbTaskTheoryLibrary>().lambda().eq(TbTaskTheoryLibrary::getChapterId, id));
            if(i<1){
                return ResultResponse.FAILED("删除失败");
            }
            //发送到同步es的队列
            for (TbTaskTheoryLibrary library : list) {
                mqTemplate.convertAndSend(THEORY_QUEUE,library.getTheoryId()+",del");
            }
        }
        return ResultResponse.SUCCESS();
    }

    @Override
    public ResultResponse listTaskTheoryLibrary(ListParamVo paramVo) {
        //非空判断
        if(paramVo.getParamMap().size()==0 || paramVo.getParamMap().get("schoolId")==null){
            return ResultResponse.FAILED("无效查询条件");
        }
        //分页
        IPage<TbTaskTheoryLibrary> page = new Page<>(paramVo.getCurrent(), paramVo.getSize());

        //理论标题 题目类型 课程ID 章节ID 录入教师ID 空处理
        if(StringUtils.checkValNull(paramVo.getParamMap().get("theoryTitle"))){
            paramVo.getParamMap().put("theoryTitle","");
        }
        if(StringUtils.checkValNull(paramVo.getParamMap().get("theoryType"))){
            paramVo.getParamMap().put("theoryType","");
        }
        if(StringUtils.checkValNull(paramVo.getParamMap().get("chapterId"))){
            paramVo.getParamMap().put("chapterId","");
        }
        if(StringUtils.checkValNull(paramVo.getParamMap().get("courseId"))){
            paramVo.getParamMap().put("courseId","");
        }
        if(StringUtils.checkValNull(paramVo.getParamMap().get("teacherId"))){
            paramVo.getParamMap().put("teacherId","");
        }

        IPage<TaskTheoryVo> selectPage = theoryMapper.selectTaskTheoryLibraryList(page,paramVo.getParamMap());
        return ResultResponse.SUCCESS(selectPage);
    }

    @Override
    public ResultResponse getTaskTheoryById(TbTaskTheoryLibrary taskTheoryLibrary) {
        return ResultResponse.SUCCESS(theoryMapper.selectById(taskTheoryLibrary.getTheoryId()));
    }

    @Override
    public ResultResponse saveTaskSkillLibrary(TbTaskSkillLibrary tbTaskSkillLibrary) {
        int i = skillMapper.insert(tbTaskSkillLibrary);
        if(i<1){
            return ResultResponse.FAILED("新增失败");
        }
        return ResultResponse.SUCCESS(skillMapper.selectById(tbTaskSkillLibrary.getSkillId()));
    }

    @Override
    public ResultResponse deleteTaskSkillBySkillId(BatchChooseIdVo chooseIdVo) {
        if (ChooseIsNull.idsIsNull(chooseIdVo)){
            return ResultResponse.FAILED("未选择要删除的数据");
        }
        int i = skillMapper.deleteBatchIds(chooseIdVo.getIds());
        if(i<1){
            return ResultResponse.FAILED("删除失败");
        }
        return ResultResponse.SUCCESS();
    }

    @Override
    public ResultResponse updateTaskSkillLibrary(TbTaskSkillLibrary tbTaskSkillLibrary) {
        String nowTime = MyTimeUtil.getNowTimeToString();
        tbTaskSkillLibrary.setUpdateTime(nowTime);
        int i = skillMapper.updateById(tbTaskSkillLibrary);
        if(i<1){
            return ResultResponse.FAILED("修改失败");
        }
        return ResultResponse.SUCCESS(skillMapper.selectById(tbTaskSkillLibrary.getSkillId()));
    }

    @Override
    public ResultResponse listTaskSkillLibrary(ListParamVo paramVo) {
        //非空判断
        if(paramVo.getParamMap().size()==0 || paramVo.getParamMap().get("schoolId")==null){
            return ResultResponse.FAILED("无效查询条件");
        }

        IPage<TbTaskSkillDetail> page = new Page<>(paramVo.getCurrent(), paramVo.getSize());

        //技能标题 课程ID 章节ID 录入教师ID 空处理
        if(StringUtils.checkValNull(paramVo.getParamMap().get("skillTitle"))){
            paramVo.getParamMap().put("skillTitle","");
        }
        if(StringUtils.checkValNull(paramVo.getParamMap().get("courseId"))){
            paramVo.getParamMap().put("courseId","");
        }
        if(StringUtils.checkValNull(paramVo.getParamMap().get("chapterId"))){
            paramVo.getParamMap().put("chapterId","");
        }
        if(StringUtils.checkValNull(paramVo.getParamMap().get("teacherId"))){
            paramVo.getParamMap().put("teacherId","");
        }

        IPage<TaskSkillVo> list = skillMapper.selectTaskSkillLibraryList(page,paramVo.getParamMap());
        return ResultResponse.SUCCESS(list);
    }

    @Override
    public ResultResponse saveTaskSkillDetail(List<TbTaskSkillDetail> detailList) {
        if(detailList==null || detailList.size()==0){
            return ResultResponse.FAILED("无新增数据");
        }
        for (TbTaskSkillDetail detail : detailList) {
            detailMapper.insert(detail);
        }
        return ResultResponse.SUCCESS();
    }

    @Override
    public ResultResponse deleteTaskSkillDetail(BatchChooseIdVo chooseIdVo) {
        if (ChooseIsNull.idsIsNull(chooseIdVo)){
            return ResultResponse.FAILED("未选择要删除的数据");
        }
        int i = detailMapper.deleteBatchIds(chooseIdVo.getIds());
        if(i<1){
            return ResultResponse.FAILED("删除失败");
        }
        return ResultResponse.SUCCESS();
    }

    @Override
    public ResultResponse updateTaskSkillDetail(TbTaskSkillDetail tbTaskSkillDetail) {
        String nowTime = MyTimeUtil.getNowTimeToString();
        tbTaskSkillDetail.setUpdateTime(nowTime);
        int i = detailMapper.updateById(tbTaskSkillDetail);
        if(i<1){
            return ResultResponse.FAILED("修改失败");
        }
        return ResultResponse.SUCCESS(detailMapper.selectById(tbTaskSkillDetail.getSkillDetailId()));
    }

    @Override
    public ResultResponse listTaskSkillDetail(ListParamVo paramVo) {
        //非空判断
        if(paramVo.getParamMap().size()==0 || paramVo.getParamMap().get("skillId")==null){
            return ResultResponse.FAILED("无效查询条件");
        }

        Page<TbTaskSkillDetail> page = new Page<>(paramVo.getCurrent(), paramVo.getSize());

        Page<TbTaskSkillDetail> selectPage = detailMapper.selectPage(page,
                new QueryWrapper<TbTaskSkillDetail>().lambda().eq(TbTaskSkillDetail::getSkillId, paramVo.getParamMap().get("skillId")));
        return ResultResponse.SUCCESS(selectPage);
    }

    @Override
    public ResultResponse saveTaskChapter(TbTaskChapter tbTaskChapter) {
        TbTaskChapter selectOne = chapterMapper.selectOne(
                new QueryWrapper<TbTaskChapter>().lambda().eq(TbTaskChapter::getChapterName, tbTaskChapter.getChapterName())
                        .eq(TbTaskChapter::getSchoolId, tbTaskChapter.getSchoolId())
        );
        if(selectOne!=null){
            return ResultResponse.FAILED("新增失败,该章节已存在!");
        }
        int i = chapterMapper.insert(tbTaskChapter);
        if(i<1){
            return ResultResponse.FAILED("新增失败");
        }
        return ResultResponse.SUCCESS(chapterMapper.selectById(tbTaskChapter.getChapterId()));
    }

    @Override
    public ResultResponse deleteTaskChapter(BatchChooseIdVo chooseIdVo) {
        if (ChooseIsNull.idsIsNull(chooseIdVo)){
            return ResultResponse.FAILED("未选择要删除的数据");
        }
        int i = chapterMapper.deleteBatchIds(chooseIdVo.getIds());
        if(i<1){
            return ResultResponse.FAILED("删除失败");
        }
        return ResultResponse.SUCCESS();
    }

    @Override
    public ResultResponse updateTaskChapter(TbTaskChapter tbTaskChapter) {
        TbTaskChapter selectOne = chapterMapper.selectOne(
                new QueryWrapper<TbTaskChapter>().lambda().eq(TbTaskChapter::getChapterName, tbTaskChapter.getChapterName())
                        .eq(TbTaskChapter::getSchoolId, tbTaskChapter.getSchoolId())
        );
        if(selectOne!=null && !selectOne.getChapterId().equals(tbTaskChapter.getChapterId())){
            return ResultResponse.FAILED(0,"修改失败,该章节已存在!");
        }
        String nowTime = MyTimeUtil.getNowTimeToString();
        tbTaskChapter.setUpdateTime(nowTime);
        int i = chapterMapper.updateById(tbTaskChapter);
        if(i<1){
            return ResultResponse.FAILED(0,"修改失败");
        }
        return ResultResponse.SUCCESS(chapterMapper.selectById(tbTaskChapter.getChapterId()));
    }

    @Override
    public ResultResponse listTaskChapter(ListParamVo paramVo) {
        //非空判断
        if(paramVo.getParamMap().size()==0 || paramVo.getParamMap().get("schoolId")==null){
            return ResultResponse.FAILED("无效查询条件");
        }

        Page<TbTaskChapter> page = new Page<>(paramVo.getCurrent(), paramVo.getSize());

        QueryWrapper<TbTaskChapter> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TbTaskChapter::getSchoolId,paramVo.getParamMap().get("schoolId"));

        if(StringUtils.checkValNotNull(paramVo.getParamMap().get("chapterName"))){
            queryWrapper.lambda().like(TbTaskChapter::getChapterName,paramVo.getParamMap().get("chapterName"));
        }

        Page<TbTaskChapter> selectPage = chapterMapper.selectPage(page, queryWrapper);
        return ResultResponse.SUCCESS(selectPage);
    }

    @Override
    public ResultResponse listAllTaskChapter() {
        return ResultResponse.SUCCESS(chapterMapper.selectList(null));
    }

    @Override
    public ResultResponse getTaskTaskTheory(TbTaskTheoryLibrary tbTaskTheoryLibrary) {
        if(StringUtils.checkValNull(tbTaskTheoryLibrary.getTheoryId())){
            return ResultResponse.FAILED("ID为空");
        }
        return ResultResponse.SUCCESS(theoryMapper.selectById(tbTaskTheoryLibrary.getTheoryId()));
    }

    @Override
    public ResultResponse getTaskTaskSkill(TbTaskSkillLibrary tbTaskSkillLibrary) {
        if(StringUtils.checkValNull(tbTaskSkillLibrary.getSkillId())){
            return ResultResponse.FAILED("ID为空");
        }
        return ResultResponse.SUCCESS(skillMapper.selectById(tbTaskSkillLibrary.getSkillId()));
    }

    @Override
    public ResultResponse randomCreateTheory(RandomTheoryVo randomVo) {
        if(randomVo==null || StringUtils.checkValNull(randomVo.getSchoolId())){
            return ResultResponse.FAILED("生成条件错误!");
        }

        long start = System.currentTimeMillis();

        

        TheoryParam param = new TheoryParam();

        //学院ID
        param.setSchoolId(randomVo.getSchoolId());

        //章节ID集合
        if(StringUtils.checkValNotNull(randomVo.getChapterIds())){
            param.setChapterIdsToS(randomVo.getChapterIds().toString().substring(1,randomVo.getChapterIds().toString().length()-1));
        }
        //课程ID集合
        if(StringUtils.checkValNotNull(randomVo.getCourseIds())){
            param.setCourseIdsTos(randomVo.getCourseIds().toString().substring(1,randomVo.getCourseIds().toString().length()-1));
        }
        //录入教师ID集合
        if(StringUtils.checkValNotNull(randomVo.getTeacherIds())){
            param.setTeacherIdsToS(randomVo.getTeacherIds().toString().substring(1,randomVo.getTeacherIds().toString().length()-1));
        }


        //判断试题难度等级
        if(StringUtils.checkValNull(randomVo.getLevel()) || randomVo.getLevel()==0){
            //随机难度
            HashMap<String, Object> map = new HashMap<>();
            Set<TbTaskTheoryLibrary> set = new HashSet<>();
            //获取所有符合条件的试题 按类型分别获取
            if(randomVo.getSize1()!=null && randomVo.getSize1()>0){
                param.setTheoryType("1-单选题");
                List<TbTaskTheoryLibrary> list1 = theoryMapper.selectTheoryList(param);
                if(list1.size()<randomVo.getSize1()){
                    return ResultResponse.FAILED("作业生成失败,符合条件单选题作业数量不足!");
                }
                //随机处理 利用hutool封装的随机工具
                Set<TbTaskTheoryLibrary> set1 = RandomUtil.randomEleSet(list1, randomVo.getSize1());
                set.addAll(set1);
            }
            if(randomVo.getSize2()!=null && randomVo.getSize2()>0){
                param.setTheoryType("2-多选题");
                List<TbTaskTheoryLibrary> list2 = theoryMapper.selectTheoryList(param);
                if(list2.size()<randomVo.getSize2()){
                    return ResultResponse.FAILED("作业生成失败,符合条件多选题作业数量不足!");
                }
                Set<TbTaskTheoryLibrary> set2 = RandomUtil.randomEleSet(list2, randomVo.getSize2());
                set.addAll(set2);
            }
            if(randomVo.getSize3()!=null && randomVo.getSize3()>0){
                param.setTheoryType("0-判断题");
                List<TbTaskTheoryLibrary> list3 = theoryMapper.selectTheoryList(param);
                if(list3.size()<randomVo.getSize3()){
                    return ResultResponse.FAILED("作业生成失败,符合条件判断题作业数量不足!");
                }
                Set<TbTaskTheoryLibrary> set3 = RandomUtil.randomEleSet(list3, randomVo.getSize3());
                set.addAll(set3);
            }

            //计算总难度系数
            int sum=0;
            double totalLv;
            for (TbTaskTheoryLibrary library : set) {
                sum+=library.getLevel();
            }
            totalLv=((int)((sum*1.0/set.size())*100))/100.0;

            map.put("theoryData",set);
            map.put("testNumber",set.size());
            map.put("degree",totalLv);
            log.info("总题数:{},总难度系数:{}",set.size(),totalLv);
            long end = System.currentTimeMillis();
            log.info("总耗时:{}ms",end-start);
            return ResultResponse.SUCCESS(map);

        }else {
            //根据各类型题目数量和总难度级别 计算 各个难度应该出多少题
            //难度级别 0 随机 1:1-2 , 2:2.5-3.5 3:4-5
            //根据难度级别 生成难度系数范围
            double minHard,maxHard;
            switch (randomVo.getLevel()){
                case 1:
                    minHard=1;
                    maxHard=2;
                    break;
                case 2:
                    minHard=2.5;
                    maxHard=3.5;
                    break;
                case 3:
                    minHard=4;
                    maxHard=5;
                    break;
                default:
                    return ResultResponse.FAILED("难度级别错误");
            }
            log.info("难度级别{},难度系数范围:{}-{}",randomVo.getLevel(),minHard,maxHard);

            Set<TbTaskTheoryLibrary> set1 = new HashSet<>();
            Set<TbTaskTheoryLibrary> set2 = new HashSet<>();
            Set<TbTaskTheoryLibrary> set3 = new HashSet<>();

            if(randomVo.getSize1()!=null && randomVo.getSize1()!=0){
                List<LvCountVo> list1 = getNumber(minHard, maxHard, randomVo.getSize1(),"单选题");
                for (LvCountVo countVo : list1) {
                    if(countVo.getCount()!=0){
                        param.setTheoryType("1-单选题");
                        Set<TbTaskTheoryLibrary> set = getData(param, countVo);
                        if(set==null){
                            return ResultResponse.FAILED("符合条件的试题数量不足,请重新生成");
                        }
                        set3.addAll(set);
                    }
                }
            }
            if(randomVo.getSize2()!=null && randomVo.getSize2()!=0){
                List<LvCountVo> list2 = getNumber(minHard, maxHard, randomVo.getSize2(),"多选题");
                for (LvCountVo countVo : list2) {
                    if(countVo.getCount()!=0){
                        param.setTheoryType("2-多选题");
                        Set<TbTaskTheoryLibrary> set = getData(param, countVo);
                        if(set==null){
                            return ResultResponse.FAILED("符合条件的试题数量不足,请重新生成");
                        }
                        set3.addAll(set);
                    }
                }
            }
            if(randomVo.getSize3()!=null && randomVo.getSize3()!=0){
                List<LvCountVo> list3 = getNumber(minHard, maxHard, randomVo.getSize3(),"判断题");
                for (LvCountVo countVo : list3) {
                    if(countVo.getCount()!=0){
                        param.setTheoryType("0-判断题");
                        Set<TbTaskTheoryLibrary> set = getData(param, countVo);
                        if(set==null){
                            return ResultResponse.FAILED("符合条件的试题数量不足,请重新生成");
                        }
                        set3.addAll(set);
                    }
                }
            }
            HashMap<String, Object> map = new HashMap<>();
            Set<TbTaskTheoryLibrary> set = new HashSet<>();
            set.addAll(set1);
            set.addAll(set2);
            set.addAll(set3);

            //计算总难度系数
            int sum=0;
            double totalLv;
            for (TbTaskTheoryLibrary library : set) {
                sum+=library.getLevel();
            }
            totalLv=((int)((sum*1.0/set.size())*100))/100.0;

            map.put("theoryData",set);
            map.put("testNumber",set.size());
            map.put("degree",totalLv);
            log.info("总题数:{},总难度系数:{}",set.size(),totalLv);
            long end = System.currentTimeMillis();
            log.info("总耗时:{}ms",end-start);
            return ResultResponse.SUCCESS(map);
        }

    }
    //查询符合条件的集合 并生成随机set
    public Set<TbTaskTheoryLibrary> getData(TheoryParam param,LvCountVo countVo){
        param.setLevel(countVo.getLv());
        List<TbTaskTheoryLibrary> list = theoryMapper.selectTheoryList(param);
        try {
            Set<TbTaskTheoryLibrary> set = RandomUtil.randomEleSet(list, countVo.getCount());
            return set;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    //根据难度级别 题目数量 生成各个难度题目数量的集合
    public List<LvCountVo> getNumber(double minHard,double maxHard,int number,String type){
        ArrayList<LvCountVo> list = new ArrayList<>();

        log.info(type+"-->开始随机组题:{}",MyTimeUtil.getNowTimeToString());
        long start = System.currentTimeMillis();
        //初始化难度系数
        double level=0;
        //初始化次数
        int count=0;
        //计算出各个难度数量
        int lv1=0;
        int lv2=0;
        int lv3=0;
        int lv4=0;
        int lv5=0;

        for(int i=1;i<=number;i++){
            //生成1-5的随机数 代表某个难度等级的题目数量+1
            int c = RandomUtil.randomInt(1, 6);
            switch (c){
                case 1:
                    lv1++;
                    break;
                case 2:
                    lv2++;
                    break;
                case 3:
                    lv3++;
                    break;
                case 4:
                    lv4++;
                    break;
                case 5:
                    lv5++;
                    break;
            }
            //判断难度系数是否符合
            if(i==number){
                //统计次数
                count++;
                //计算难度系数
                level=(lv1*1+lv2*2+lv3*3+lv4*4+lv5*5)*1.0/number;
                //难度系数不符合 初始化参数 继续计算
                if(level<minHard || level>maxHard){
                    level=0;
                    i=0;
                    lv1=0;
                    lv2=0;
                    lv3=0;
                    lv4=0;
                    lv5=0;
                }
                //符合则结束循环
            }
        }

        //把各个难度及对应数量加入集合
        log.info(type+"-->各难度数量:{},{},{},{},{}",lv1,lv2,lv3,lv4,lv5);
        list.add(new LvCountVo(1,lv1));
        list.add(new LvCountVo(2,lv2));
        list.add(new LvCountVo(3,lv3));
        list.add(new LvCountVo(4,lv4));
        list.add(new LvCountVo(5,lv5));

        long end = System.currentTimeMillis();
        log.info(type+"-->当前难度系数:{}",level);
        log.info(type+"-->随机组题次数:{}",count);
        log.info(type+"-->随机组题耗时:{} ms",end-start);
        log.info(type+"-->结束随机组题:{}",MyTimeUtil.getNowTimeToString());
        return list;
    }

    @Override
    public ResultResponse uploadSkillFile(MultipartFile file) throws IOException {
        if (file==null|| file.getSize()==0){
            log.info("文件为空");
            return ResultResponse.FAILED("请选择文件，重新上传");
        }
        String filename = file.getOriginalFilename();
        if (!(filename.endsWith(".doc")|| filename.endsWith(".docx"))){
            log.info("文件上传格式错误，请重新上传");
            return ResultResponse.FAILED("文件上传格式错误，重新上传");
        }

        return null;
    }

    @Override
    public ResultResponse createTheoryToEsIndex() {
        boolean b = esTemplate.indexOps(TaskTheoryEs.class).exists();
        if(!b){
            esTemplate.indexOps(TaskTheoryEs.class).create();
            Document document = esTemplate.indexOps(TaskTheoryEs.class).createMapping();
            esTemplate.indexOps(TaskTheoryEs.class).putMapping(document);
        }
        return ResultResponse.SUCCESS();
    }

    @Override
    @Transactional
    public void timingTheoryToEs() {

        try {
            List<TaskTheoryEs> list = theoryMapper.selectAllTheoryNotToEs();
            if(list.size()==0){
                log.info("没有需要同步的数据");
            }
            for (TaskTheoryEs theoryEs : list) {
                esTemplate.save(theoryEs);
                theoryMapper.updateToEsById(theoryEs.getTheoryId());
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.info("理论作业库同步失败");
        }
        log.info("理论作业库同步成功");
    }

    @Override
    public ResultResponse listTaskTheoryLibraryByEs(ListParamVo paramVo) {
        //非空判断
        if(paramVo.getParamMap().size()==0 || StringUtils.checkValNull(paramVo.getParamMap().get("schoolId"))){
            return ResultResponse.FAILED("无效查询条件");
        }

        //分页
        Pageable pageable = PageRequest.of(paramVo.getCurrent()-1,paramVo.getSize());

        //条件查询
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.termQuery("schoolId",paramVo.getParamMap().get("schoolId")));

        if(StringUtils.checkValNotNull(paramVo.getParamMap().get("theoryTitle"))){
            boolQueryBuilder.must(QueryBuilders.matchQuery("theoryTitle",paramVo.getParamMap().get("theoryTitle")));
        }
        if(StringUtils.checkValNotNull(paramVo.getParamMap().get("theoryType"))){
            boolQueryBuilder.must(QueryBuilders.termQuery("theoryType",paramVo.getParamMap().get("theoryType")));
        }
        //高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.preTags("<b style='color:red;'>").postTags("</b>").field("theoryTitle");

        //查询数据
        NativeSearchQueryBuilder builder = new NativeSearchQueryBuilder();
        NativeSearchQuery searchQuery = builder.withQuery(boolQueryBuilder).withPageable(pageable).withHighlightBuilder(highlightBuilder).build();
        SearchHits<TaskTheoryEs> search = esTemplate.search(searchQuery, TaskTheoryEs.class);

        //生成返回数据
        Map<String, Object> map = new HashMap<>();
        map.put("total",search.getTotalHits());
        List<TaskTheoryEs> list = new ArrayList<>();

        //处理高亮
        for (SearchHit<TaskTheoryEs> searchHit : search) {
            TaskTheoryEs content = searchHit.getContent();
            if(searchHit.getHighlightField("theoryTitle").size()>0){
                content.setTheoryTitle(searchHit.getHighlightField("theoryTitle").get(0));
            }
            list.add(content);
        }
        map.put("records",list);

        return ResultResponse.SUCCESS(map);
    }

}




